package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.domain.Login;
import cn.itsource.ymcc.domain.User;
import cn.itsource.ymcc.domain.UserAccount;
import cn.itsource.ymcc.domain.UserBaseInfo;
import cn.itsource.ymcc.dto.CodeDto;
import cn.itsource.ymcc.dto.RegisterDTO;
import cn.itsource.ymcc.exception.ErrorCode;
import cn.itsource.ymcc.feignclient.UAAFeignClient;
import cn.itsource.ymcc.mapper.UserMapper;
import cn.itsource.ymcc.result.JSONResult;
import cn.itsource.ymcc.service.IUserAccountService;
import cn.itsource.ymcc.service.IUserBaseInfoService;
import cn.itsource.ymcc.service.IUserService;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.util.BitStatesUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.UUID;

import static cn.itsource.ymcc.constant.ReidsConstant.SMS_CODE_KEY;
import static org.springframework.transaction.annotation.Propagation.REQUIRED;
import static org.springframework.transaction.annotation.Propagation.SUPPORTS;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author gwk
 * @since 2023-08-01
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private IUserBaseInfoService userBaseInfoService;

    @Autowired
    private IUserAccountService userAccountService;

    @Autowired
    private UAAFeignClient uaaFeignClient;


    // 注册前台用户
    @Override
    //分布式事务注解
    @GlobalTransactional(rollbackFor = Exception.class)
    public void register(RegisterDTO registerDTO) {
//        1. 基本参数校验 -- JS303
        String smsCode = registerDTO.getSmsCode();
        String mobile = registerDTO.getMobile();
        String password = registerDTO.getPassword();
        String regChannel = registerDTO.getRegChannel();

        AssertUtil.isPhone(mobile,"手机格式不正确");
        // 2. 手机验证码校验 -- 通过Redis获取smsCode
        String key = String.format(SMS_CODE_KEY, mobile);
        CodeDto codeDto = (CodeDto) redisTemplate.opsForValue().get(key);
        //2.1 codeDto 是否存在
        AssertUtil.isNotNull(codeDto, ErrorCode.SMS_CODE_EXPIRE);
        //2.2 codeDto 是否正确
        AssertUtil.isEquals(smsCode, codeDto.getCode(), ErrorCode.SMS_CODE_ERROR);

        // 3. 手机是否已经被注册校验);
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("phone", mobile);
        User userTable = selectOne(wrapper);
        AssertUtil.isNull(userTable, ErrorCode.USER_ALREADY_EXIST);
//        4. 远程保存login登录信息[Feign远程调用]
        Login login = new Login();
        login.setUsername(mobile);
        login.setPassword(password);
        login.setType(Integer.valueOf(regChannel));

        JSONResult register = uaaFeignClient.register(login);
        log.info("远程调用UAA服务，register:{}", register);
        // 判断Logn 是否保存成功，失败着不继续保持user
        AssertUtil.isTrue(register.isSuccess(), ErrorCode.UAA_REGISTER_ERROR);

//        5. 保存user注册信息
        User user = new User();
        Date date = new Date();
        user.setCreateTime(date.getTime());
        user.setPhone(mobile);
        user.setNickName(mobile);
        // 初始状态
        user.setBitState(BitStatesUtils.OP_REGISTED);
        // 设置手机号绑定成功
        user.setBitState(BitStatesUtils.addState(user.getBitState(), BitStatesUtils.OP_AUTHED_PHONE));
        user.setSecLevel(0);
        user.setLoginId(Long.valueOf(register.getData().toString()));
        // 保存用户表 // MybatisPlus 保存成功的对象，自动返回自增长id ,到user对象中
        insert(user);

//        6. 保存user_base_info基本信息
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setId(user.getId());
        userBaseInfo.setCreateTime(date.getTime());
        userBaseInfo.setRegChannel(Integer.valueOf(regChannel));
        userBaseInfo.setLevel(0);
        userBaseInfo.setGrowScore(0);

        userBaseInfoService.insert(userBaseInfo);

      int i = 1/0;
//        7. 保存user_account账户
        UserAccount  userAccount = new UserAccount();
        userAccount.setId(user.getId());
        userAccount.setCreateTime(date.getTime());
        userAccount.setUsableAmount(new BigDecimal(0));
        userAccount.setFrozenAmount(new BigDecimal(0));
        userAccount.setPassword(null);

        userAccountService.insert(userAccount);

//        8. 删除Redis中的手机验证码
        redisTemplate.delete(key);
    }
}
